<template>
  <div class="operation-logs">
    <div class="logs-header">
      <div class="header-left">
        <el-icon class="header-icon">
          <Document />
        </el-icon>
        <span class="header-title">操作日志</span>
        <el-tag :type="wsConnected ? 'success' : 'danger'" size="small">
          {{ wsConnected ? 'WebSocket已连接' : 'WebSocket未连接' }}
        </el-tag>
      </div>
      
      <div class="header-right">
        <el-button-group>
          <el-button 
            size="small" 
            :icon="Refresh"
            @click="refreshLogs"
            :loading="refreshing"
          >
            刷新
          </el-button>
          <el-button 
            size="small" 
            :icon="Delete"
            @click="clearLogs"
            type="danger"
          >
            清空
          </el-button>
        </el-button-group>
      </div>
    </div>

    <!-- 过滤器 -->
    <div class="filters">
      <el-row :gutter="16">
        <el-col :span="8">
          <el-select
            v-model="filters.level"
            placeholder="日志级别"
            clearable
            size="small"
            style="width: 100%"
          >
            <el-option label="全部" value="" />
            <el-option label="INFO" value="INFO" />
            <el-option label="WARNING" value="WARNING" />
            <el-option label="ERROR" value="ERROR" />
          </el-select>
        </el-col>
        
        <el-col :span="8">
          <el-select
            v-model="filters.operation"
            placeholder="操作类型"
            clearable
            size="small"
            style="width: 100%"
          >
            <el-option label="全部" value="" />
            <el-option 
              v-for="op in operationTypes" 
              :key="op" 
              :label="op" 
              :value="op" 
            />
          </el-select>
        </el-col>
        
        <el-col :span="8">
          <el-select
            v-model="filters.success"
            placeholder="成功状态"
            clearable
            size="small"
            style="width: 100%"
          >
            <el-option label="全部" value="" />
            <el-option label="成功" :value="true" />
            <el-option label="失败" :value="false" />
          </el-select>
        </el-col>
      </el-row>
    </div>

    <!-- 日志列表 -->
    <div class="logs-container" ref="logsContainer">
      <div v-if="filteredLogs.length === 0" class="empty-logs">
        <el-empty description="暂无日志数据" />
      </div>
      
      <div v-else class="logs-list">
        <div
          v-for="log in filteredLogs"
          :key="log.id"
          :class="['log-item', getLogLevelClass(log.level)]"
          @click="showLogDetail(log)"
        >
          <div class="log-header">
            <div class="log-time">
              {{ formatTime(log.timestamp) }}
            </div>
            <div class="log-badges">
              <el-tag 
                :type="getLogLevelType(log.level)" 
                size="small"
                effect="dark"
              >
                {{ log.level }}
              </el-tag>
              <el-tag 
                :type="log.success ? 'success' : 'danger'" 
                size="small"
                effect="plain"
              >
                {{ log.success ? '成功' : '失败' }}
              </el-tag>
            </div>
          </div>
          
          <div class="log-content">
            <div class="log-operation">
              <el-tag type="info" size="small">
                {{ log.operation }}
              </el-tag>
            </div>
            <div class="log-message">
              {{ log.message }}
            </div>
            <div v-if="log.details" class="log-details">
              <el-icon class="details-icon">
                <InfoFilled />
              </el-icon>
              <span>点击查看详情</span>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 滚动控制 -->
    <div class="scroll-controls">
      <el-checkbox 
        v-model="autoScroll" 
        size="small"
        @change="onAutoScrollChange"
      >
        自动滚动
      </el-checkbox>
      <el-button 
        size="small" 
        :icon="ArrowDown"
        @click="scrollToBottom"
      >
        滚动到底部
      </el-button>
    </div>

    <!-- 日志详情对话框 -->
    <el-dialog
      v-model="detailDialogVisible"
      :title="`日志详情 - ${currentLog?.operation}`"
      width="70%"
      :close-on-click-modal="false"
    >
      <div v-if="currentLog" class="log-detail-content">
        <el-descriptions :column="2" border>
          <el-descriptions-item label="时间">
            {{ formatFullTime(currentLog.timestamp) }}
          </el-descriptions-item>
          <el-descriptions-item label="级别">
            <el-tag :type="getLogLevelType(currentLog.level)">
              {{ currentLog.level }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="操作">
            {{ currentLog.operation }}
          </el-descriptions-item>
          <el-descriptions-item label="状态">
            <el-tag :type="currentLog.success ? 'success' : 'danger'">
              {{ currentLog.success ? '成功' : '失败' }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="消息" :span="2">
            {{ currentLog.message }}
          </el-descriptions-item>
        </el-descriptions>
        
        <div v-if="currentLog.details" class="details-section">
          <h4>详细信息</h4>
          <pre class="details-json">{{ JSON.stringify(currentLog.details, null, 2) }}</pre>
        </div>
      </div>

      <template #footer>
        <el-button @click="detailDialogVisible = false">关闭</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script>
import { ref, reactive, computed, onMounted, onUnmounted, nextTick } from 'vue'
import { logAPI } from '@/utils/api'
import { useWebSocket } from '@/utils/websocket'
import { ElMessage } from 'element-plus'
import { 
  Document, Refresh, Delete, InfoFilled, ArrowDown 
} from '@element-plus/icons-vue'
import dayjs from 'dayjs'

export default {
  name: 'OperationLogs',
  components: {
    Document, Refresh, Delete, InfoFilled, ArrowDown
  },
  setup() {
    // WebSocket连接
    const { connected: wsConnected, connect, disconnect, on, off } = useWebSocket()
    
    // 响应式数据
    const logs = ref([])
    const refreshing = ref(false)
    const autoScroll = ref(true)
    const logsContainer = ref()
    
    // 过滤器
    const filters = reactive({
      level: '',
      operation: '',
      success: ''
    })
    
    // 操作类型列表
    const operationTypes = ref([])
    
    // 对话框
    const detailDialogVisible = ref(false)
    const currentLog = ref(null)
    
    // 计算属性
    const filteredLogs = computed(() => {
      let filtered = logs.value
      
      // 按级别过滤
      if (filters.level) {
        filtered = filtered.filter(log => log.level === filters.level)
      }
      
      // 按操作类型过滤
      if (filters.operation) {
        filtered = filtered.filter(log => log.operation === filters.operation)
      }
      
      // 按成功状态过滤
      if (filters.success !== '') {
        filtered = filtered.filter(log => log.success === filters.success)
      }
      
      return filtered
    })
    
    // 方法
    const formatTime = (timestamp) => {
      return dayjs(timestamp).format('HH:mm:ss')
    }
    
    const formatFullTime = (timestamp) => {
      return dayjs(timestamp).format('YYYY-MM-DD HH:mm:ss')
    }
    
    const getLogLevelClass = (level) => {
      return `log-level-${level.toLowerCase()}`
    }
    
    const getLogLevelType = (level) => {
      switch (level) {
        case 'ERROR':
          return 'danger'
        case 'WARNING':
          return 'warning'
        case 'INFO':
        default:
          return 'success'
      }
    }
    
    const refreshLogs = async () => {
      refreshing.value = true
      try {
        const response = await logAPI.getLogs({ limit: 500 })
        if (response.success) {
          logs.value = response.data
          ElMessage.success('日志刷新成功')
          
          // 更新操作类型列表
          updateOperationTypes()
          
          // 如果开启自动滚动，滚动到底部
          if (autoScroll.value) {
            await nextTick()
            scrollToBottom()
          }
        }
      } catch (error) {
        ElMessage.error('刷新日志失败: ' + error.message)
      } finally {
        refreshing.value = false
      }
    }
    
    const clearLogs = async () => {
      try {
        await logAPI.clearLogs()
        logs.value = []
        operationTypes.value = []
        ElMessage.success('日志已清空')
      } catch (error) {
        ElMessage.error('清空日志失败: ' + error.message)
      }
    }
    
    const showLogDetail = (log) => {
      currentLog.value = log
      detailDialogVisible.value = true
    }
    
    const scrollToBottom = () => {
      if (logsContainer.value) {
        logsContainer.value.scrollTop = logsContainer.value.scrollHeight
      }
    }
    
    const onAutoScrollChange = () => {
      if (autoScroll.value) {
        scrollToBottom()
      }
    }
    
    const updateOperationTypes = () => {
      const types = [...new Set(logs.value.map(log => log.operation))]
      operationTypes.value = types.sort()
    }
    
    const addLog = (logData) => {
      // 添加新日志到列表
      logs.value.push(logData)
      
      // 保持日志数量限制
      if (logs.value.length > 1000) {
        logs.value = logs.value.slice(-1000)
      }
      
      // 更新操作类型列表
      updateOperationTypes()
      
      // 如果开启自动滚动，滚动到底部
      if (autoScroll.value) {
        nextTick(() => {
          scrollToBottom()
        })
      }
    }
    
    const handleWebSocketMessage = (data) => {
      addLog(data)
    }
    
    const handleWebSocketError = (error) => {
      console.error('WebSocket错误:', error)
    }
    
    const handleWebSocketDisconnected = () => {
      console.log('WebSocket连接断开')
    }
    
    // 初始化
    onMounted(async () => {
      // 连接WebSocket
      connect()
      
      // 监听WebSocket事件
      on('log', handleWebSocketMessage)
      on('error', handleWebSocketError)
      on('disconnected', handleWebSocketDisconnected)
      
      // 初始加载日志
      await refreshLogs()
    })
    
    onUnmounted(() => {
      // 移除WebSocket事件监听
      off('log', handleWebSocketMessage)
      off('error', handleWebSocketError)
      off('disconnected', handleWebSocketDisconnected)
      
      // 断开WebSocket连接
      disconnect()
    })
    
    return {
      logs,
      filteredLogs,
      refreshing,
      autoScroll,
      logsContainer,
      filters,
      operationTypes,
      detailDialogVisible,
      currentLog,
      wsConnected,
      formatTime,
      formatFullTime,
      getLogLevelClass,
      getLogLevelType,
      refreshLogs,
      clearLogs,
      showLogDetail,
      scrollToBottom,
      onAutoScrollChange
    }
  }
}
</script>

<style scoped>
.operation-logs {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 16px;
}

.logs-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
  padding-bottom: 8px;
  border-bottom: 1px solid #e4e7ed;
}

.header-left {
  display: flex;
  align-items: center;
  gap: 8px;
}

.header-icon {
  color: #409eff;
  font-size: 18px;
}

.header-title {
  font-weight: 600;
  font-size: 16px;
}

.header-right {
  display: flex;
  gap: 8px;
}

.filters {
  margin-bottom: 16px;
}

.logs-container {
  flex: 1;
  overflow-y: auto;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  background-color: #fafafa;
}

.empty-logs {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.logs-list {
  padding: 8px;
}

.log-item {
  background-color: white;
  border-radius: 4px;
  padding: 12px;
  margin-bottom: 8px;
  cursor: pointer;
  transition: all 0.2s;
  border-left: 4px solid #e4e7ed;
}

.log-item:hover {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transform: translateY(-1px);
}

.log-item.log-level-error {
  border-left-color: #f56c6c;
}

.log-item.log-level-warning {
  border-left-color: #e6a23c;
}

.log-item.log-level-info {
  border-left-color: #67c23a;
}

.log-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}

.log-time {
  font-size: 12px;
  color: #909399;
  font-family: monospace;
}

.log-badges {
  display: flex;
  gap: 4px;
}

.log-content {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.log-operation {
  margin-bottom: 4px;
}

.log-message {
  font-size: 14px;
  line-height: 1.4;
  color: #303133;
}

.log-details {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: #909399;
  margin-top: 4px;
}

.details-icon {
  font-size: 12px;
}

.scroll-controls {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 12px;
  padding-top: 8px;
  border-top: 1px solid #e4e7ed;
}

.log-detail-content {
  max-height: 600px;
  overflow-y: auto;
}

.details-section {
  margin-top: 16px;
}

.details-section h4 {
  margin-bottom: 8px;
  color: #303133;
}

.details-json {
  background-color: #f5f7fa;
  padding: 12px;
  border-radius: 4px;
  font-size: 12px;
  line-height: 1.4;
  max-height: 300px;
  overflow-y: auto;
}

/* 滚动条样式 */
.logs-container::-webkit-scrollbar {
  width: 6px;
}

.logs-container::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 3px;
}

.logs-container::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 3px;
}

.logs-container::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .logs-header {
    flex-direction: column;
    gap: 12px;
  }
  
  .header-left,
  .header-right {
    width: 100%;
    justify-content: center;
  }
  
  .scroll-controls {
    flex-direction: column;
    gap: 8px;
  }
  
  .log-item {
    padding: 8px;
  }
  
  .log-header {
    flex-direction: column;
    gap: 8px;
  }
}
</style> 